﻿using EasyNet.Componets.Core;
using EasyNet.Componets.Core.Domain;
using EasyNet.Componets.Core.Extensions;
using EasyNet.Componets.Core.Pagers;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace EasyNet.Componets.Data.EntityFramework
{
    /// <summary>
    /// Entity Framework 仓储实现
    /// </summary>
    /// <typeparam name="TAggregateRoot">聚合根类型</typeparam>
    public class EntityFrameworkRepository<TAggregateRoot> : IRepository<TAggregateRoot>
        where TAggregateRoot : class, IAggregateRoot
    {
        protected readonly IEntityFrameworkRepositoryContext Context;

        public EntityFrameworkRepository(IRepositoryContext context)
        {
            var efContext = context as IEntityFrameworkRepositoryContext;

            if (efContext == null)
            {
                throw new ArgumentException("The Context must be implement the IEntityFrameworkRepositoryContext interface");
            }

            Context = efContext;
        }


        #region Add
        public void Add(TAggregateRoot aggregateRoot)
        {
            Context.RegisterNew(aggregateRoot);
        }
        #endregion

        #region Update
        /// <summary>
        /// 更新指定的聚合根。
        /// </summary>
        /// <param name="aggregateRoot">需要更新的聚合根。</param>
        public void Update(TAggregateRoot aggregateRoot)
        {
            Context.RegisterModified(aggregateRoot);
        }
        #endregion

        #region Remove
        /// <summary>
        /// 将指定的聚合根从仓储中移除。
        /// </summary>
        /// <param name="aggregateRoot">需要从仓储中移除的聚合根。</param>
        /// 
        public void Remove(TAggregateRoot aggregateRoot)
        {
            Context.RegisterDeleted(aggregateRoot);
        }
        #endregion

        #region Get 

        public TAggregateRoot GetByKey(string key)
        {
            var query = GetQueryable(noTracking: false);
            var obj = query.FirstOrDefault(c => c.Id == key);
            return obj;
        }
        
        /// <summary>
        /// 通过条件获取聚合根
        /// </summary>
        /// <param name="wherePredicate">过滤条件</param>
        /// <returns>聚合根实例。</returns>
        public TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> wherePredicate)
        {
            return Get(wherePredicate, true, false);
        }

        /// <summary>
        /// 通过条件获取聚合根
        /// </summary>
        /// <param name="wherePredicate">过滤条件</param>
        /// <param name="includeNav">初始化立即加载的关联对象</param>
        /// <param name="noTracking">EF是否不跟踪对象</param>
        /// <returns>聚合根实例。</returns>
        public TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> wherePredicate, bool includeNav, bool noTracking)
        {
            var query = GetQueryable(noTracking: false);
            if(wherePredicate == null)
            {
                return query.FirstOrDefault();
            }
            return query.Where(wherePredicate).FirstOrDefault();
        }

        #endregion

        #region Exist
        /// <summary>
        /// 返回一个<see cref="Boolean"/>值，该值表示符合指定规约条件的聚合根是否存在。
        /// </summary>
        /// <param name="wherePredicate">过滤条件</param>
        /// <returns>如果符合指定规约条件的聚合根存在，则返回true，否则返回false。</returns>
        public bool Exist(Expression<Func<TAggregateRoot, bool>> wherePredicate)
        {
            //判断是否存在，不需要立即加载关联对象
            return GetQueryable(false).Any(wherePredicate);
        }
        #endregion

        #region List
        /// <summary>
        /// 获取所有聚合根列表
        /// </summary>
        /// <returns>聚合根实例列表</returns>
        public List<TAggregateRoot> List()
        {
            var query = GetQueryable(true, false);
            return query.ToList();
        }

        /// <summary>
        /// 通过条件获取聚合根列表
        /// </summary>
        /// <param name="specification">条件参数</param>
        /// <returns>聚合根实例列表</returns>
        public List<TAggregateRoot> List(Expression<Func<TAggregateRoot, bool>> wherePredicate)
        {
            return List(wherePredicate, true, false);
        }

        /// <summary>
        /// 通过条件获取聚合根列表
        /// </summary>
        /// <param name="specification">条件参数</param>
        /// <param name="includeNav">初始化立即加载的关联对象</param>
        /// <param name="noTracking">EF是否不跟踪对象</param>
        /// <returns>聚合根实例列表</returns>
        public List<TAggregateRoot> List(Expression<Func<TAggregateRoot, bool>> wherePredicate, bool includeNav, bool noTracking)
        {
            if (wherePredicate == null) return List();

            var query = GetQueryable(includeNav, noTracking);
            return query.Where(wherePredicate).ToList();
        }

        /// <summary>
        /// 根据指定的规约，以指定的排序字段和排序方式，以及分页参数，从仓储中读取所有聚合根。
        /// </summary>
        /// <param name="pagerQuery">分页查询</param>
        /// <returns>分页结果</returns>
        public PagerResult<TAggregateRoot> ListInPage(PagerQuery pagerQuery)
        {
            return ListInPage(pagerQuery, true, false);
        }

        /// <summary>
        /// 根据指定的规约，以指定的排序字段和排序方式，以及分页参数，从仓储中读取所有聚合根。
        /// </summary>
        /// <param name="pagerQuery">分页查询</param>
        /// <param name="includeNav">初始化立即加载的关联对象</param>
        /// <param name="noTracking">EF是否不跟踪对象</param>
        /// <returns>分页结果</returns>
        public PagerResult<TAggregateRoot> ListInPage(PagerQuery pagerQuery, bool includeNav, bool noTracking)
        {
            var pageIndex = 1;
            var pageSize = 20;
            var totalRecords = 0;
            List<TAggregateRoot> data = new List<TAggregateRoot>();
            if(pagerQuery == null)
            {
                data = List(null, includeNav, noTracking).ToList();
                totalRecords = data.Count;
            }
            if(pagerQuery.PageIndex > 0)
            {
                pageIndex = pagerQuery.PageIndex;
            }
            if(pagerQuery.PageSize > 0)
            {
                pageSize = pagerQuery.PageSize;
            }

            //去掉查询条件为Value为Null或者Empty
            var removeList = pagerQuery.ConditiaonList.Where(w => w.Value.IsNullOrEmpty()).ToList();
            for (int i = 0; i < removeList.Count; i++)
            {
                pagerQuery.ConditiaonList.Remove(removeList[i]);
            }

            IQueryable<TAggregateRoot> query = GetQueryable(includeNav, noTracking);
            //获取属性
            var type = typeof(TAggregateRoot);
            PropertyInfo[] properties = type.GetPropertyInfoWithCache();
            var where = ConvertPagerQueryCondition(pagerQuery.ConditiaonList, properties);
            if(where != null)
            {
                query = query.Where(where);
            }
            //统计总记录数
            totalRecords = query.Count();
            int totalPages = (totalRecords + pageSize - 1) / pageSize;

            IOrderedQueryable<TAggregateRoot> orderQuery = null;
            //排序
            //排序
            if (pagerQuery.SortList != null && pagerQuery.SortList.Count != 0)
            {
                var firstSort = pagerQuery.SortList[0];
                orderQuery = OrderBy(query, firstSort, properties);

                for (int i = 1; i < pagerQuery.SortList.Count; i++)
                {
                    orderQuery = OrderBy(orderQuery, pagerQuery.SortList[i], properties);
                }
            }
            else
            {
                throw new Exception("分页查询没有排序！");
            }
            if (orderQuery == null)
            {
                throw new Exception("分页查询排序匹配失败！");
            }
            //分页查询
            int skip = (pageIndex - 1) * pageSize;
            int take = pageSize;
            data = orderQuery.Skip(skip).Take(take).ToList();

            return new PagerResult<TAggregateRoot>(pageIndex, pageSize, totalRecords, data);
        }


        private Expression<Func<TAggregateRoot, bool>> ConvertPagerQueryCondition(List<PagerCondition> conditiaonList, PropertyInfo[] properties)
        {
            Expression<Func<TAggregateRoot, bool>> predicate = null;
            if (conditiaonList == null || conditiaonList.Count == 0) return predicate;

            //将condition字段跟聚合跟属性进行匹配
            var conditionPropertyDic = MapConditionProperty(conditiaonList, properties);
            if (conditionPropertyDic.Count == 0) return predicate;

            string parameterName = "w";
            var firstConditionProperty = conditionPropertyDic.First();

            var express = BuildExpression(firstConditionProperty.Key, firstConditionProperty.Value, parameterName);
            conditionPropertyDic.Remove(firstConditionProperty.Key);

            foreach (var item in conditionPropertyDic)
            {
                var expressJoin = BuildExpression(item.Key, item.Value, parameterName);
                if (item.Key.Join.ToLower() == ConditionJoinType.Add)
                {
                    express = express.And(expressJoin);
                }
                else if (item.Key.Join.ToLower() == ConditionJoinType.Or)
                {
                    express = express.Or(expressJoin);
                }
                else
                {
                    throw new Exception(string.Format("can not find the ConditionJoinType: {0}", item.Key.Join));
                }
            }

            predicate = express;
            return predicate;
        }

        private Dictionary<PagerCondition, PropertyInfo> MapConditionProperty(List<PagerCondition> conditiaonList, PropertyInfo[] properties)
        {
            var dic = new Dictionary<PagerCondition, PropertyInfo>();
            conditiaonList.ForEach(item =>
            {
                if (item == null || item.Field.IsNullOrEmpty()
                || item.Filter.IsNullOrEmpty() || item.Join.IsNullOrEmpty())
                {
                    throw new Exception(string.Format("PagerCondition object or properties can not be null"));
                }
                var property = MapProperty(item.Field, item.FieldSplitedArray, properties);
                dic.Add(item, property);
            });

            return dic;
        }

        private Expression<Func<TAggregateRoot, bool>> BuildExpression(PagerCondition condition, PropertyInfo property, string parameterName)
        {
            Expression<Func<TAggregateRoot, bool>> lambda = null;

            switch (condition.Filter.ToLower())
            {
                case ConditionFilterType.Equal:
                    lambda = LambdaBuilder.Equal<TAggregateRoot>(property, parameterName, condition.Value, condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.NotEqual:
                    lambda = LambdaBuilder.NotEqual<TAggregateRoot>(property, parameterName, condition.Value, condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.LessThan:
                    lambda = LambdaBuilder.LessThan<TAggregateRoot>(property, parameterName, condition.Value, condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.LessThanOrEqual:
                    lambda = LambdaBuilder.LessThanOrEqual<TAggregateRoot>(property, parameterName, condition.Value, condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.GreaterThan:
                    lambda = LambdaBuilder.GreaterThan<TAggregateRoot>(property, parameterName, condition.Value, condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.GreaterThanOrEqual:
                    lambda = LambdaBuilder.GreaterThanOrEqual<TAggregateRoot>(property, parameterName, condition.Value, condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.Like:
                    lambda = LambdaBuilder.Contains<TAggregateRoot>(property, parameterName, condition.Value, condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.NotLike:
                    lambda = LambdaBuilder.NotContains<TAggregateRoot>(property, parameterName, condition.Value, condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.In:
                    lambda = LambdaBuilder.InCollection<TAggregateRoot>(property, parameterName, condition.ValueSplitedArray.ToList(), condition.FieldSplitedArray);
                    break;
                case ConditionFilterType.NotIn:
                    lambda = LambdaBuilder.NotInCollection<TAggregateRoot>(property, parameterName, condition.ValueSplitedArray.ToList(), condition.FieldSplitedArray);
                    break;
                default:
                    throw new Exception(string.Format("can not find the ConditionFilterType: {0}", condition.Filter));
            }

            return lambda;
        }

        private PropertyInfo MapProperty(string field, string[] fieldArray, PropertyInfo[] properties)
        {
            var property = properties.FirstOrDefault(f => f.Name.ToLower() == fieldArray[0].ToLower().Trim());
            if (property == null)
            {
                throw new Exception(string.Format("{1} can not find the property: {0}", field, typeof(TAggregateRoot).FullName));
            }
            if (fieldArray.Length > 1)
            {
                Type subType = property.PropertyType;
                for (var i = 1; i < fieldArray.Length; i++)
                {
                    var subProperties = subType.GetPropertyInfoWithCache();
                    var subField = fieldArray[i].ToLower().Trim();
                    var subProperty = subProperties.FirstOrDefault(f => f.Name.ToLower() == subField);
                    if (subProperty == null)
                    {
                        throw new Exception(string.Format("{1} can not find the property: {0}", field, typeof(TAggregateRoot).FullName));
                    }
                }
            }
            return property;
        }

        private IOrderedQueryable<TAggregateRoot> OrderBy(IOrderedQueryable<TAggregateRoot> query, PagerSort sort, PropertyInfo[] properties)
        {
            var property = MapProperty(sort.Field, sort.FieldSplitedArray, properties);


            #region MyRegion
            if (property.PropertyType == typeof(string))
            {
                Expression<Func<TAggregateRoot, string>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, string>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(long))
            {
                Expression<Func<TAggregateRoot, long>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, long>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(long?))
            {
                Expression<Func<TAggregateRoot, long?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, long?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(int))
            {
                Expression<Func<TAggregateRoot, int>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, int>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(int?))
            {
                Expression<Func<TAggregateRoot, int?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, int?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(bool))
            {
                Expression<Func<TAggregateRoot, bool>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, bool>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(bool?))
            {
                Expression<Func<TAggregateRoot, bool?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, bool?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(decimal))
            {
                Expression<Func<TAggregateRoot, decimal>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, decimal>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(decimal?))
            {
                Expression<Func<TAggregateRoot, decimal?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, decimal?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(float))
            {
                Expression<Func<TAggregateRoot, float>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, float>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(float?))
            {
                Expression<Func<TAggregateRoot, float?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, float?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(double))
            {
                Expression<Func<TAggregateRoot, double>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, double>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(double?))
            {
                Expression<Func<TAggregateRoot, double?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, double?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(DateTime))
            {
                Expression<Func<TAggregateRoot, DateTime>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, DateTime>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(DateTime?))
            {
                Expression<Func<TAggregateRoot, DateTime?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, DateTime?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(short))
            {
                Expression<Func<TAggregateRoot, short>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, short>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(short?))
            {
                Expression<Func<TAggregateRoot, short?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, short?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(byte))
            {
                Expression<Func<TAggregateRoot, byte>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, byte>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(byte?))
            {
                Expression<Func<TAggregateRoot, byte?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, byte?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            else
            {
                var orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, dynamic>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    query = query.ThenByDescending(orderByExpression);
                }
                else
                {
                    query = query.ThenBy(orderByExpression);
                }
            }
            #endregion
            return query;
        }

        private IOrderedQueryable<TAggregateRoot> OrderBy(IQueryable<TAggregateRoot> query, PagerSort sort, PropertyInfo[] properties)
        {
            IOrderedQueryable<TAggregateRoot> orderQuery = null;
            var property = MapProperty(sort.Field, sort.FieldSplitedArray, properties);

            #region MyRegion
            if (property.PropertyType == typeof(string))
            {
                Expression<Func<TAggregateRoot, string>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, string>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(long))
            {
                Expression<Func<TAggregateRoot, long>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, long>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(long?))
            {
                Expression<Func<TAggregateRoot, long?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, long?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(int))
            {
                Expression<Func<TAggregateRoot, int>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, int>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(int?))
            {
                Expression<Func<TAggregateRoot, int?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, int?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(bool))
            {
                Expression<Func<TAggregateRoot, bool>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, bool>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(bool?))
            {
                Expression<Func<TAggregateRoot, bool?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, bool?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(decimal))
            {
                Expression<Func<TAggregateRoot, decimal>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, decimal>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(decimal?))
            {
                Expression<Func<TAggregateRoot, decimal?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, decimal?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(float))
            {
                Expression<Func<TAggregateRoot, float>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, float>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(float?))
            {
                Expression<Func<TAggregateRoot, float?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, float?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(double))
            {
                Expression<Func<TAggregateRoot, double>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, double>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(double?))
            {
                Expression<Func<TAggregateRoot, double?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, double?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(DateTime))
            {
                Expression<Func<TAggregateRoot, DateTime>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, DateTime>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(DateTime?))
            {
                Expression<Func<TAggregateRoot, DateTime?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, DateTime?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(short))
            {
                Expression<Func<TAggregateRoot, short>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, short>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(short?))
            {
                Expression<Func<TAggregateRoot, short?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, short?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(byte))
            {
                Expression<Func<TAggregateRoot, byte>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, byte>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else if (property.PropertyType == typeof(byte?))
            {
                Expression<Func<TAggregateRoot, byte?>> orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, byte?>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            else
            {
                var orderByExpression = LambdaBuilder.CreatePropertyExpression<TAggregateRoot, dynamic>(property, "o", sort.FieldSplitedArray);
                if (sort.OrderBy == OrderByType.Desc)
                {
                    orderQuery = query.OrderByDescending(orderByExpression);
                }
                else
                {
                    orderQuery = query.OrderBy(orderByExpression);
                }
            }
            #endregion

            return orderQuery;
        }
        #endregion



        #region Protected

        /// <summary>
        /// Do eager load inclues.
        /// 此方法用于立即加载关联对象
        /// </summary>
        /// <param name="query">query</param>
        /// <returns>query that includes eager loading.</returns>
        protected virtual IQueryable<TAggregateRoot> IncludeNav(IQueryable<TAggregateRoot> query)
        {
            return query;
        }

        /// <summary>
        /// 获取IQueryable对象
        /// </summary>
        /// <param name="includeNav">初始化立即加载的关联对象</param>
        /// <param name="noTracking">EF是否不跟踪对象</param>
        /// <returns>IQueryable对象</returns>
        protected IQueryable<TAggregateRoot> GetQueryable(bool includeNav = true, bool noTracking = true)
        {
            var query = AsQueryable();

            if (noTracking)
            {
                query = query.AsNoTracking();
            }

            if (includeNav)
            {
                //初始化需要立即加载的关联对象
                query = this.IncludeNav(query);
            }

            return query;
        }

        protected IQueryable<TAggregateRoot> AsQueryable()
        {
            return Context.Context.Set<TAggregateRoot>().AsQueryable();
        }
        #endregion


    }
}
